import { Component, OnInit, AfterViewInit, OnDestroy } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd';
import { DataRegister } from 'src/app/models';
import { BaseService, DataRegisterService } from 'src/app/services';
import { EventManagerService } from 'src/app/services/event-manager.service';
import { OrganizationService } from 'src/app/services/organization.service';
import { UploadService } from 'src/app/services/upload.service';
import { PermitConfig, PermitConfigId } from '../../../models';
import { EngineService } from '../../../services/engine.service';
import { BaseFieldComponent } from '../base-field/base-field.component';
import { v4 as UUID } from 'uuid';
import { WorkflowPageService } from 'src/app/common/page-render/workflow-page-container/workflow-page.service';
import { DataRPermits } from 'src/app/models/dataRPermits';
import { compareDataField } from 'src/app/common/tools/condition-tool';

@Component({
  selector: 'zepride-auto-form',
  templateUrl: './auto-form.component.html',
  styleUrls: ['./auto-form.component.less', '../field.common.less']
})
export class AutoFormComponent extends BaseFieldComponent implements OnInit, AfterViewInit, OnDestroy {

  rows: any[][] = [];
  showBorder = true;
  permitConfig: PermitConfig[] = [
    { mode: 'query', permitId: '查看', permitName: '', authObjectId: '' },
    { mode: 'edit', permitId: '编辑', permitName: '', authObjectId: '' }
  ];

  get bindData() {
    const bindField = this.componentData.bindField;
    if (bindField) {
      const list = this.formatData();
      this.dataModel[bindField] = list;
      return this.dataModel[bindField];
    } else {
      return this.componentData.defaultValue;
    }
  }

  get bindDataFromModel() {
    const bindField = this.componentData.bindField;
    if (bindField) {
      return this.dataModel[bindField];
    } else {
      return this.componentData.defaultValue;
    }
  }
  editable = true;
  dataRegisterDatas = [];

  constructor(
    protected engineService: EngineService,
    protected baseSvr: BaseService,
    protected eventSvr: EventManagerService,
    protected orgSvr: OrganizationService,
    public uploadService: UploadService,
    protected msg: NzMessageService,
    public dataRegisterService: DataRegisterService,
    private workflowPageService: WorkflowPageService
  ) {
    super(engineService, baseSvr, eventSvr, orgSvr, uploadService, msg, dataRegisterService);
  }

  ngOnInit() {
    if (!this.componentData.extends.fields) {
      this.componentData.extends.fields = [];
    }
    if (this.componentData.extends.border == 'no') {
      this.showBorder = false;
    }

    this.filterRefAuto();

    if (this.bindDataFromModel) {
      for (let i = 0; i < this.bindDataFromModel.length; i++) {
        const item = this.bindDataFromModel[i];
        // tslint:disable-next-line: forin
        for (const key in item) {
          const keyFinal = `${this.componentData.bindField}[${i}].${key}`;
          this.dataModel[keyFinal] = item[key];
        }
      }
    }

    let list = this.formatData();
    if (list && list.length == 0) {
      list = this.bindDataFromModel;
    }
    this.dataRegisterDatas = this.getInitDataRegisters();
    if (list && list.length > 0) {
      for (const item of list) {
        this.addRow(item, false);
      }
    } else {
      this.addRow();
    }
    this.eventSvr.callEvents('AutoForm.filterComs', this.componentData.extends.fields);
  }

  filterRefAuto() {
    if (this.componentData.extends.refTmpComItem) {
      // 表示关联其他的自动表单数据
      const refTmpComItem = this.componentData.extends.refTmpComItem.component;
      let sourceValue: any[] = this.dataModel[refTmpComItem.bindField];

      if (sourceValue) {
        if (this.componentData.extends.refTmpComItemCondition) {
          sourceValue = sourceValue.filter(x => compareDataField(x, this.componentData.extends.refTmpComItemCondition));
        }
        this.dataModel[this.componentData.bindField] = sourceValue;
      }
    }
  }

  ngAfterViewInit() {
    setTimeout(() => {
      const authData = this.setAuthorityData();
      this.zeprideAuthorityData = {
        ...authData,
        afterChecked: this.afterAuthChecked.bind(this)
      };
    });
    this.registerModelChange();
  }

  private formatData() {
    const list = [];
    for (let i = 0; i < this.rows.length; i++) {
      const obj = {};
      const row = this.rows[i];
      for (let rowItem of row) {
        const component = rowItem.component;
        if (!component.bindField) continue;
        if (component.selector == "auto-form") {
          const bindField: string = component.bindField;
          const fields = bindField.split('.');
          obj[rowItem.sourceBindField] = this.dataModel[fields[1]];
        }
        else {
          obj[rowItem.sourceBindField] = this.dataModel[component.bindField];
        }
      }
      list.push(obj);
    }
    return list;
  }

  getInitDataRegisters() {
    const result = [];
    if (this.componentData.bindField) {
      const data = this.dataModel[this.componentData.bindField];
      if (data && data.length) {
        data.forEach((item: { dataRegisterData: any; }) => {
          if (item.dataRegisterData) {
            result.push(item.dataRegisterData);
          }
        });
      }
    }
    return result;
  }

  addRow(defaultValues?: any[], needAddDataRegister = true) {
    if (!this.editable) {
      return;
    }
    const row = [];
    if (this.componentData.extends.fields) {
      // tslint:disable-next-line: prefer-for-of
      for (let i = 0; i < this.componentData.extends.fields.length; i++) {
        let fieldItem = this.componentData.extends.fields[i];
        fieldItem = JSON.parse(JSON.stringify(fieldItem));
        if (!fieldItem.component) {
          continue;
        }
        const bindField = fieldItem.component.bindField;
        fieldItem.sourceBindField = bindField;

        const fieldKey = `${this.componentData.bindField}[${this.rows.length}].${bindField}`;
        fieldItem.component.bindField = fieldKey;

        if (defaultValues) {
          fieldItem.component.defaultValue = defaultValues[bindField];
        }
        row.push(fieldItem);
      }
      this.rows.push(row);
      const childFlowId = this.componentData.extends.childrenWorkflowId;
      if (childFlowId && needAddDataRegister) {
        const dataRegisterData = this.generateChildFlowDataRegister(childFlowId);
        this.dataRegisterDatas.push(dataRegisterData);
      }
    }

    this.setTableData();
  }

  delRow(index: number) {
    if (this.rows.length == 1) {
      return;
    }
    const row = this.rows[index];
    for (let rowItem of row) {
      const key = rowItem.component.bindField;
      delete this.dataModel[key];
    }
    this.rows.splice(index, 1);

    const childFlowId = this.componentData.extends.childrenWorkflowId;
    if (childFlowId) {
      const dataRegisterData = this.dataRegisterDatas[index];
      if (dataRegisterData && dataRegisterData.dataRegister && dataRegisterData.dataRegister.id) {
        this.dataRegisterDatas.splice(index, 1);
        if (!dataRegisterData.dataRegister.fresh) {
          this.dataRegisterService.deleteDataRegister(dataRegisterData.dataRegister.id);
        }
      }
    }

    this.setTableData();
  }

  pageSavedHandle = async () => {
    const data = this.formatData();
    await this.setDataregisters(data);
    if (!this.componentData.bindField || !data.length) {
      return;
    }
    this.dataModel[this.componentData.bindField] = data;
    this.generateOutputHtml();
  }

  setTableData() {
    const data = this.formatData();
    if (!this.componentData.bindField || !data.length) {
      return;
    }

    this.setBindData(data);
  }

  generateOutputHtml() {
    if (!this.componentData.bindField) { return; }
    const tableHeader: string[] = [];
    if (!this.componentData.extends.hideNo) {
      tableHeader.push(`<th nzAlign="center">序号</th>`);
    }
    for (const item of this.componentData.extends.fields) {
      if (item.isOutput == false) continue;
      tableHeader.push(`<th nzAlign="center">${item.name}</th>`);
    }
    const tableBody: string[] = [];
    for (let i = 0; i < this.rows.length; i++) {
      const row = [];
      if (!this.componentData.extends.hideNo) {
        row.push(`<td>${(i + 1) + ''}</td>`);
      }

      const rowItem = this.rows[i];
      for (let j = 0; j < rowItem.length; j++) {
        const rowDataItem = rowItem[j];
        if (rowDataItem.isOutput == false) { continue; }
        const data = this.getRowColumValue(j, rowDataItem);
        row.push(`<td>${data}</td>`);
      }

      tableBody.push('<tr>' + row.join('') + '</tr>');
    }

    const dataTableHtml = `<table>
      <thead>
        <tr>${tableHeader.join('')}</tr>
      </thead>
      <tbody>
        ${tableBody.join('')}
      </tbody>
    </table>`;

    this.dataModel[this.componentData.bindField + 'html'] = dataTableHtml;
  }

  /**
   * 构建子流程的dataRegister
   * @param childFlowId 子流程id
   */
  generateChildFlowDataRegister(childFlowId: string): {
    dataRegister: DataRegister;
    datarPermits: DataRPermits[];
  } {
    const parentRegisterId = this.workflowPageService.currentDataRegisterId;
    let childDataRegister: DataRegister;
    if (parentRegisterId) {
      const id = UUID().replace(/-/g, '');
      childDataRegister = {
        id,
        objectId: childFlowId,
        objectType: 'childrenWorkflow',
        dataType: 'workflowOrder',
        parentDataRegisterId: parentRegisterId,
        fresh: true, // 是否还未保存的标识，用于删除判断
        data: {}
      } as any;
    }
    return { dataRegister: childDataRegister, datarPermits: [] };
  }
  /**
   * 把dataRegister保存到数据中
   * @param data 格式化后的数据
   */
  async setDataregisters(data: any[]) {
    const childFlowId = this.componentData.extends.childrenWorkflowId;
    if (childFlowId) {
      const taskMemberComponent = this.getTaskMemberComponent();
      this.dataRegisterDatas.forEach((item, index) => {
        delete item.dataRegister.fresh;
        const row = this.rows[index];
        const fields = this.getRowFieldValues(row);
        item.dataRegister.data.fields = fields;
        if (taskMemberComponent) {
          const bindField = taskMemberComponent.bindField;
          const userIds = fields[bindField];
          item.dataRegister.userIds = userIds;
        }
      });
      const dataRegisters = await this.createDataRegisters(this.dataRegisterDatas);
      data.forEach((item, index) => {
        item.dataRegisterData = dataRegisters[index];
      });
    }
  }
  /**
   * 获取单行的数据
   * @param row 单行
   */
  getRowFieldValues(row: any[]) {
    const result = {} as any;
    if (row && row.length) {
      row.forEach(item => {
        const bindFiled: string = item.component.bindField;
        if (bindFiled) {
          const fieldArray = bindFiled.split('.');
          const realField = fieldArray[1];
          if (realField) {
            const field = realField.split('#')[0];
            if (field) {
              const value = this.dataModel[bindFiled] ? this.dataModel[bindFiled] : '';
              result[field] = value;
            }
          }
        }
      });
    }
    return result;
  }
  /**
   * 批量创建datRegister
   * @param params 请求参数
   */
  createDataRegisters(params: {
    dataRegister: DataRegister;
    datarPermits: DataRPermits[];
  }[]) {
    return this.dataRegisterService.createDataRegsiters(params);
  }

  getChangeLogSource() {
    const list: string[] = (this.dataChangeLog.sourceValue as Array<any>).map((x, index) => {
      const result = [];
      // tslint:disable-next-line: forin
      for (const key in x) {
        result.push(`${key}:${x[key]}`);
      }
      return '第' + (index + 1) + '行：' + result.join(' | ');
    });
    return list.join('\n');
  }

  getChangeLogTarget() {
    const list: string[] = (this.dataChangeLog.targetValue as Array<any>).map((x, index) => {
      const result = [];
      // tslint:disable-next-line: forin
      for (const key in x) {
        result.push(`${key}:${x[key]}`);
      }
      return '第' + (index + 1) + '行：' + result.join(' | ');
    });
    return list.join('\n');
  }

  afterAuthChecked(params: {
    permitId: PermitConfigId;
    isAuthorized: boolean;
  }) {
    if (!params.isAuthorized && params.permitId === '编辑') {
      this.editable = false;
    }
  }

  getRowColumValue(index: number, rowItem): string {
    try {
      const obj = this.dataModel[this.componentData.bindField];
      if (!obj) { return ''; }
      const value = obj[index][rowItem.sourceBindField];
      return value;
    } catch (error) {
      return '';
    }
  }

  getTaskMemberComponent() {
    const childFlowId = this.componentData.extends.childrenWorkflowId;
    const taskMemberField = this.componentData.extends.fields.find(field => field.component && field.component.selector === 'task-member');
    if (childFlowId && taskMemberField) {
      return taskMemberField.component;
    } else {
      return false;
    }
  }

  registerModelChange() {
    this.modelChange$ = this.engineService.dataModelChange$.subscribe(data => {
      if (data.identifyId !== this.componentData.identifyId) {
        if (this.componentData.extends.refTmpComItem && data.tmpComItemId == this.componentData.extends.refTmpComItem.tplComponentTempId) {
          this.ngOnInit();
        }
      }
    });
  }

  ngOnDestroy(): void {
    if (this.modelChange$) {
      this.modelChange$.unsubscribe();
    }
  }
}
